package com.itfreer.gis.server.vector.generate;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.referencing.FactoryException;

import com.itfreer.gis.server.vector.generate.pipeline.ClipRemoveDegenerateGeometries;
import com.itfreer.gis.server.vector.generate.pipeline.CollapseCollections;
import com.itfreer.gis.server.vector.generate.pipeline.Simplify;

/**
 * Geometry 处理接口构建器
 */
public class PipelineBuilder {

	/**
	 * 切片范围
	 */
	private ReferencedEnvelope renderingArea;

	private Pipeline first = Pipeline.END, last = Pipeline.END;

	/**
	 * @param renderingArea    The extent of the tile in target CRS
	 * @param paintArea        The extent of the tile in screen/pixel coordinates
	 * @param sourceCrs        The CRS of the features
	 * @param overSampleFactor Divisor for simplification tolerance.
	 */
	public static PipelineBuilder newBuilder(ReferencedEnvelope renderingArea) throws FactoryException {
		PipelineBuilder builder = new PipelineBuilder();
		builder.renderingArea = renderingArea;
		return builder;
	}

	private PipelineBuilder() {
	}

	/**
	 * 构建
	 * 
	 * @return
	 */
	public Pipeline build() {
		return first;
	}

	/**
	 * 添加下一个
	 * 
	 * @param step
	 */
	private void addLast(Pipeline step) {
		if (first == Pipeline.END) {
			first = step;
			last = first;
		} else {
			last.setNext(step);
			last = step;
		}
	}

	/**
	 * Flatten singleton feature collections
	 * 
	 * @return
	 */
	public PipelineBuilder collapseCollections() {
		addLast(new CollapseCollections());
		return this;
	}

	/**
	 * Simplify the geometry
	 */
	public PipelineBuilder simplify(int z) {
		double size = 0D;
		switch (z) {
		case 9:
			size = 0.0001D;
			break;
		case 10:
			size = 0.0001D;
			break;
		case 11:
			size = 0.0001D;
			break;
		case 12:
			size = 0.0001D;
			break;
		case 13:
			size = 0.0001D;
			break;
		case 14:
			size = 0.00001D;
			break;
		case 15:
			size = 0.000005D;
			break;
		default:
			break;
		}
		addLast(new Simplify(size));
		return this;
	}

	/**
	 * Clip to the area of the tile plus its gutter
	 */
	public PipelineBuilder clip() {
		double size = 0.001;
		renderingArea.expandBy(size);
		addLast(new ClipRemoveDegenerateGeometries(renderingArea));
		return this;
	}
}
